/**
 * gnome-gmail-notifier: the gnome gmail notifier.
 * Copyright (C) 2007 Bradley A. Worley.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the
 * 
 *     Free Software Foundation, Inc.
 *     59 Temple Place, Suite 330
 *     Boston, MA 02111-1307 USA
 **/

/*
 * include our application header.
 */
#include <main.h>

/*
 * private object definition.
 */
struct _GgnPreferencesPrivate {
    /* the (default) gconf client. */
    GConfClient* conf;
};

/*
 * forward function definitions.
 */
static void ggn_preferences_init (GgnPreferences* self);
static void ggn_preferences_class_init (GgnPreferencesClass* klass);
static void ggn_preferences_finalize (GObject* obj);

/*
 * define the gobject type and its basic functions.
 */
G_DEFINE_TYPE (GgnPreferences, ggn_preferences, G_TYPE_OBJECT);

/*
 * define the signals used.
 */
enum {
    ACCOUNTS_MODIFIED,
    LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };

/*
 * ggn_preferences_keyring_attribs:
 *
 * This function removes repeated code by generating the attributes array
 * for any given username in the default keyring. If this function were not
 * available, each function would have to recreate the array itself.
 *
 * Return value: a GnomeKeyringAttributeList.
 */
GnomeKeyringAttributeList* ggn_preferences_keyring_attribs (gchar* user,
                                                            gchar* domain) {
    /* initialize the attributes list. */
    GnomeKeyringAttribute attrib;
    GnomeKeyringAttributeList* keyattribs;
    keyattribs = gnome_keyring_attribute_list_new ();
    
    /* set the "user" attribute. */
    attrib.name = g_strdup ("user");
    attrib.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
    attrib.value.string = g_strdup_printf ("%s@%s", user, domain);
    g_array_append_val (keyattribs, attrib);
    
    /* set the "server" attribute. */
    attrib.name = g_strdup ("server");
    attrib.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
    attrib.value.string = g_strdup (GGN_ATOM_FEED_SERVER);
    g_array_append_val (keyattribs, attrib);
    
    /* set the "object" attribute. */
    attrib.name = g_strdup ("object");
    attrib.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
    attrib.value.string = g_strdup (GGN_ATOM_FEED_OBJECT);
    g_array_append_val (keyattribs, attrib);
    
    /* set the "protocol" attribute. */
    attrib.name = g_strdup ("protocol");
    attrib.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
    attrib.value.string = g_strdup (GGN_ATOM_FEED_PROTOCOL);
    g_array_append_val (keyattribs, attrib);
    
    /* return the attributes array. */
    return keyattribs;
}

/*
 * ggn_preferences_keyring_create:
 *
 * This function uses gnome-keyring to create a new password entry in the
 * default keyring, updating a current entry if one exists already.
 *
 * Return value: void.
 */
void ggn_preferences_keyring_create (gchar* user, gchar* domain, gchar* pass) {
    /* define some default values for saving to gnome-keyring. */
    const gchar* desc = g_strdup_printf ("Gmail password for %s@%s",
                                         user, domain);
    const gchar* secret = g_strdup (pass);
    
    /* define some variables for saving the passphrase. */
    guint32 id;
    GnomeKeyringResult result;
    GnomeKeyringAttributeList* keyattribs = ggn_preferences_keyring_attribs (user,
                                                                             domain);
    
    /* synchronously write to the keyring. */
    result = gnome_keyring_item_create_sync (NULL, GNOME_KEYRING_ITEM_NETWORK_PASSWORD,
                                             desc, keyattribs, secret, TRUE, &id);
    
    /* free the attributes list. */
    gnome_keyring_attribute_list_free (keyattribs);
}

/*
 * ggn_preferences_keyring_find:
 *
 * This function uses gnome-keyring to find an already created password
 * entry in the default keyring, which may or may not exist.
 *
 * Return value: the passphrase.
 */
gchar* ggn_preferences_keyring_find (gchar* user, gchar* domain) {
    /* define a passphrase to be returned. */
    gchar* phrase = NULL;
    
    /* define a list of keyring search results. */
    GList* found;
    
    /* define attributes by which to search for a key. */
    GnomeKeyringFound* item;
    GnomeKeyringResult result;
    GnomeKeyringAttributeList* keyattribs = ggn_preferences_keyring_attribs (user,
                                                                             domain);
    
    /* search for the password. */
    result = gnome_keyring_find_items_sync (GNOME_KEYRING_ITEM_NETWORK_PASSWORD,
                                            keyattribs, &found);
    
    /* did we find a passphrase? */
    if (result == GNOME_KEYRING_RESULT_OK) {
        /* read the passphrase from the _first_ found item. */
        item = g_list_nth_data (found, 0);
        phrase = g_strdup (item->secret);
    }
    
    /* free the variables used for the search. */
    gnome_keyring_found_list_free (found);
    gnome_keyring_attribute_list_free (keyattribs);
    
    /* return the passphrase. */
    return phrase;
}

/*
 * ggn_preferences_keyring_delete:
 *
 * This function uses gnome-keyring to delete an already created password
 * entry in the default keyring, which may or may not exist.
 *
 * Return value: void.
 */
void ggn_preferences_keyring_delete (gchar* user, gchar* domain) {
    /* define a list of keyring search results. */
    GList* found;
    
    /* define attributes by which to search for a key. */
    GnomeKeyringFound* item;
    GnomeKeyringResult result;
    GnomeKeyringAttributeList* keyattribs = ggn_preferences_keyring_attribs (user,
                                                                             domain);
    
    /* search for the password. */
    result = gnome_keyring_find_items_sync (GNOME_KEYRING_ITEM_NETWORK_PASSWORD,
                                            keyattribs, &found);
    
    /* did we find a passphrase? */
    if (result == GNOME_KEYRING_RESULT_OK) {
        /* read the passphrase from the _first_ found item. */
        item = g_list_nth_data (found, 0);
        
        /* delete this item. */
        gnome_keyring_item_delete_sync (NULL, item->item_id);
    }
    
    /* free the variables used for the search. */
    gnome_keyring_found_list_free (found);
    gnome_keyring_attribute_list_free (keyattribs);
}

/*
 * ggn_preferences_account_new:
 *
 * Allocates a new GgnAccount structure.
 *
 * Return value: GgnAccount struct pointer.
 */
GgnAccount* ggn_preferences_account_new (void) {
    /* allocate and return the new account. */
    return g_new0 (GgnAccount, 1);
}

/*
 * ggn_preferences_account_free:
 *
 * Frees an allocated GgnAccount structure.
 *
 * Return value: void.
 */
void ggn_preferences_account_free (GgnAccount* account) {
    /* free the account objects. */
    g_free (account->name);
    g_free (account->user);
    g_free (account->domain);
    g_free (account->pass);

    /* free the account structure. */
    g_free (account);
}

/*
 * ggn_preferences_default_accounts_modified_cb:
 *
 * This is the default "accounts_modified" callback function manager.
 *
 * Return value: void.
 */
static void ggn_preferences_default_accounts_modified_cb (GgnPreferences* prefs) {
    /* exit the function. */
    return;
}

/*
 * ggn_preferences_init:
 *
 * This function is used by the gobject library to
 * generate a new instance of our object.
 */
static void ggn_preferences_init (GgnPreferences* self) {
    /* set up the private data structure. */
    self->priv = g_new0 (GgnPreferencesPrivate, 1);
    
    /* setup the gconf engine. */
    self->priv->conf = gconf_client_get_default ();
}

/*
 * ggn_preferences_class_init:
 *
 * This function is used by the gobject library to
 * generate a new class object of our object.
 */
static void ggn_preferences_class_init (GgnPreferencesClass* klass) {
    /* setup a gobject class. */
    GObjectClass* gobj_class = G_OBJECT_CLASS (klass);
    
    /* set the locations of our destruction function. */
    gobj_class->finalize = ggn_preferences_finalize;
    
    /* setup the default signal handlers. */
    klass->accounts_modified = ggn_preferences_default_accounts_modified_cb;
    
    /*
     * GgnPreferences::accounts_modified:
     *
     * Emitted when any data pertaining to accounts
     * has been changed by the application.
     */
    signals[ACCOUNTS_MODIFIED] = g_signal_new ("accounts_modified",
                                               G_OBJECT_CLASS_TYPE (gobj_class),
                                               G_SIGNAL_RUN_FIRST,
                                               G_STRUCT_OFFSET (GgnPreferencesClass,
                                                                accounts_modified),
                                               NULL, NULL,
                                               ggn_marshal_VOID__VOID,
                                               G_TYPE_NONE, 0);
}

/*
 * ggn_preferences_finalize:
 *
 * This function is used by the gobject library to cleanly finish
 * the destruction process started by the dispose function.
 */
static void ggn_preferences_finalize (GObject* obj) {
    /* make a reference to ourself. */
    GgnPreferences* self = GGN_PREFERENCES (obj);

    /* unref the gconf client. */
    g_object_unref (self->priv->conf);
    
    /* destroy the private object. */
    g_free (self->priv);
    self->priv = NULL;
    
    /* chain up to the parent class. */
    G_OBJECT_CLASS (ggn_preferences_parent_class)->finalize (obj);
}

/*
 * ggn_preferences_new:
 *
 * Creates a new GgnPreferences with default values, which are
 * used to read preferences files.
 *
 * Return value: the new preferences object.
 */
GgnPreferences* ggn_preferences_new (void) {
    /* make a newly created gobject. */
    GgnPreferences* prefs = g_object_new (GGN_TYPE_PREFERENCES, NULL);
    
    /* return the new object. */
    return prefs;
}

/*
 * ggn_preferences_free:
 *
 * Frees the given preferences object by decreasing its reference count.
 *
 * Return value: void.
 */
void ggn_preferences_free (GgnPreferences* prefs) {
    /* unreference the object. */
    while (G_IS_OBJECT (prefs)) {
        /* unreference this object. */
        g_object_unref (G_OBJECT (prefs));
    }
}

/*
 * ggn_preferences_get_accounts:
 *
 * Returns a singly-linked list of the gmail accounts that we
 * are keeping track of in the gconf database.
 *
 * Return value: Accounts list.
 */
GSList* ggn_preferences_get_accounts (GgnPreferences* prefs) {
    /* declare some helping variables. */
    GSList* accounts;

    /* get the accounts list. */
    accounts = gconf_client_get_list (prefs->priv->conf,
                                      GGN_GPREF_ACCOUNT_LIST,
                                      GCONF_VALUE_STRING,
                                      NULL);

    /* return the value. */
    return accounts;
}

/*
 * ggn_preferences_get_account:
 *
 * Returns an account structure which is identified by a
 * given email address. Because email addresses are unique,
 * they are the chosen method of indexing the accounts in
 * the gconf database.
 *
 * Return value: Account structure.
 */
GgnAccount* ggn_preferences_get_account (GgnPreferences* prefs,
                                         const gchar* email) {
    /* declare some helping variables. */
    GgnAccount* account;
    gchar* key;

    /* allocate a GgnAccount structure for use. */
    account = ggn_preferences_account_new ();

    /* query gconf for the account description. */
    key = g_strdup_printf ("%s/%s/name", GGN_GPREF_ACCOUNT_ROOT, email);
    account->name = gconf_client_get_string (prefs->priv->conf, key, NULL);
    g_free (key);

    /* query gconf for the account username. */
    key = g_strdup_printf ("%s/%s/user", GGN_GPREF_ACCOUNT_ROOT, email);
    account->user = gconf_client_get_string (prefs->priv->conf, key, NULL);
    g_free (key);

    /* query gconf for the account domain name. */
    key = g_strdup_printf ("%s/%s/domain", GGN_GPREF_ACCOUNT_ROOT, email);
    account->domain = gconf_client_get_string (prefs->priv->conf, key, NULL);
    g_free (key);

    /* query gconf for the account enabled value. */
    key = g_strdup_printf ("%s/%s/enab", GGN_GPREF_ACCOUNT_ROOT, email);
    account->enab = gconf_client_get_bool (prefs->priv->conf, key, NULL);
    g_free (key);

    /* query gconf for the account default value. */
    key = g_strdup_printf ("%s/%s/send", GGN_GPREF_ACCOUNT_ROOT, email);
    account->send = gconf_client_get_bool (prefs->priv->conf, key, NULL);
    g_free (key);

    /* see if we encountered an error. */
    if (account->name == NULL ||
        account->user == NULL ||
        account->domain == NULL) {
        /* there is no entry, most likely. */
        ggn_preferences_account_free (account);
        return NULL;
    }

    /* get the account password as well. */
    account->pass = ggn_preferences_keyring_find (account->user,
                                                  account->domain);

    /* return the account object. */
    return account;
}

/*
 * ggn_preferences_set_account:
 *
 * Saves the contents of a GgnAccount structure to the gconf
 * database for safe keeping.
 *
 * Return value: void.
 */
void ggn_preferences_set_account (GgnPreferences* prefs,
                                  GgnAccount* oldacct,
                                  GgnAccount* newacct) {
    /* define some halping variables. ;) */
    gchar* key;

    /* see if the sorting criteria changed. */
    if (g_utf8_collate (oldacct->user, newacct->user) != 0 ||
        g_utf8_collate (oldacct->domain, newacct->domain) != 0) {
        /* simply delete the old account and resave the new. */
        ggn_preferences_remove_account (prefs, oldacct, FALSE);
        ggn_preferences_add_account (prefs, newacct, TRUE);
    }
    else {
        /* if the name field has changed... */
        if (g_utf8_collate (oldacct->name, newacct->name) != 0) {
            /* update the name field. */
            key = g_strdup_printf ("%s/%s@%s/name", GGN_GPREF_ACCOUNT_ROOT,
                                   newacct->user, newacct->domain);
            gconf_client_set_string (prefs->priv->conf, key,
                                     newacct->name, NULL);
        }

        /* if the enabled field has changed... */
        if (oldacct->enab != newacct->enab) {
            /* update the enabled field. */
            key = g_strdup_printf ("%s/%s@%s/enab", GGN_GPREF_ACCOUNT_ROOT,
                                   newacct->user, newacct->domain);
            gconf_client_set_bool (prefs->priv->conf, key,
                                   newacct->enab, NULL);
        }

        /* if the default field has changed... */
        if (oldacct->send != newacct->send) {
            /* update the default field. */
            key = g_strdup_printf ("%s/%s@%s/send", GGN_GPREF_ACCOUNT_ROOT,
                                   newacct->user, newacct->domain);
            gconf_client_set_bool (prefs->priv->conf, key,
                                   newacct->send, NULL);
        }

        /* if the password has changed... */
        if (g_utf8_collate (oldacct->pass, newacct->pass) != 0) {
            /* update the password. */
            ggn_preferences_keyring_create (newacct->user,
                                            newacct->domain,
                                            newacct->pass);
        }
    }
}

/*
 * ggn_preferences_add_account:
 *
 * Adds an account with the provided descriptive name, user name,
 * and password string.
 *
 * Return value: void.
 */
void ggn_preferences_add_account (GgnPreferences* prefs,
                                  GgnAccount* account,
                                  gboolean signal) {
    /* declare helping variables. */
    GSList* accounts;
    gchar* email;
    gchar* key;

    /* generate the email string. */
    email = g_strdup_printf ("%s@%s", account->user, account->domain);

    /* get the accounts list. */
    accounts = ggn_preferences_get_accounts (prefs);

    /* add our account email to the list. */
    accounts = g_slist_append (accounts, email);
    
    /* return the list to gconf. */
    gconf_client_set_list (prefs->priv->conf,
                           GGN_GPREF_ACCOUNT_LIST,
                           GCONF_VALUE_STRING,
                           accounts, NULL);

    /* submit the account description to gconf. */
    key = g_strdup_printf ("%s/%s/name", GGN_GPREF_ACCOUNT_ROOT, email);
    gconf_client_set_string (prefs->priv->conf, key, account->name, NULL);
    g_free (key);

    /* submit the account username to gconf. */
    key = g_strdup_printf ("%s/%s/user", GGN_GPREF_ACCOUNT_ROOT, email);
    gconf_client_set_string (prefs->priv->conf, key, account->user, NULL);
    g_free (key);

    /* submit the account domain to gconf. */
    key = g_strdup_printf ("%s/%s/domain", GGN_GPREF_ACCOUNT_ROOT, email);
    gconf_client_set_string (prefs->priv->conf, key, account->domain, NULL);
    g_free (key);

    /* submit the account enabled status to gconf. */
    key = g_strdup_printf ("%s/%s/enab", GGN_GPREF_ACCOUNT_ROOT, email);
    gconf_client_set_bool (prefs->priv->conf, key, account->enab, NULL);
    g_free (key);

    /* submit the account default status to gconf. */
    key = g_strdup_printf ("%s/%s/send", GGN_GPREF_ACCOUNT_ROOT, email);
    gconf_client_set_bool (prefs->priv->conf, key, account->send, NULL);
    g_free (key);

    /* save the password in gnome-keyring. */
    ggn_preferences_keyring_create (account->user,
                                    account->domain,
                                    account->pass);

    /* free the objects. */
    g_slist_free (accounts);
    g_free (email);
    
    /* emit the "accounts_modified" signal. */
    if (signal == TRUE)
        g_signal_emit (prefs, signals[ACCOUNTS_MODIFIED], 0);
}

/*
 * ggn_preferences_remove_account:
 *
 * Removes a given account by looking it up by its ID.
 *
 * Return value: void.
 */
void ggn_preferences_remove_account (GgnPreferences* prefs,
                                     GgnAccount* account,
                                     gboolean signal) {
    /* declare helping variables. */
    GSList* accounts;
    GSList* found;
    gchar* email;
    gchar* key;

    /* form the email value. */
    email = g_strdup_printf ("%s@%s", account->user, account->domain);

    /* form the key value. */
    key = g_strdup_printf ("%s/%s@%s", GGN_GPREF_ACCOUNT_ROOT,
                           account->user, account->domain);

    /* recursively unset the gconf keys. */
    gconf_client_recursive_unset (prefs->priv->conf, key, 0, NULL);

    /* remove the passphrase from gnome-keyring. */
    ggn_preferences_keyring_delete (account->user, account->domain);

    /* get the accounts list. */
    accounts = ggn_preferences_get_accounts (prefs);

    /* make sure the accounts list exists. */
    if (accounts != NULL) {
        /* find the email entry. */
        found = g_slist_find_custom (accounts, email, (GCompareFunc)
                                     g_utf8_collate);

        /* make sure the entry exists. */
        if (found != NULL) {
            /* remove the link. */
            accounts = g_slist_remove_link (accounts, found);
            g_slist_free (found);

            /* return the list to gconf. */
            gconf_client_set_list (prefs->priv->conf,
                                   GGN_GPREF_ACCOUNT_LIST,
                                   GCONF_VALUE_STRING,
                                   accounts,
                                   NULL);
        }

        /* free the accounts list. */
        g_slist_free (accounts);
    }

    /* free the account struct and the strings. */
    ggn_preferences_account_free (account);
    g_free (email);
    g_free (key);
    
    /* emit the "accounts_modified" signal. */
    if (signal == TRUE)
        g_signal_emit (prefs, signals[ACCOUNTS_MODIFIED], 0);
}

/*
 * ggn_preferences_get_rate:
 *
 * Returns the frequency (in minutes) that the application will
 * check the user's inbox(es) for new messages.
 *
 * Return value: Update frequency.
 */
gint ggn_preferences_get_rate (GgnPreferences* prefs) {
    /* query gconf for the value. */
    gint rate = gconf_client_get_int (prefs->priv->conf,
                                      GGN_GPREF_CHECKRATE,
                                      NULL);

    /* ensure the rate is not zero. */
    if (rate <= 0)
        rate = 10;

    /* return the value. */
    return rate;
}

/*
 * ggn_preferences_get_notify_new:
 *
 * Returns whether or not the application will notify the user
 * when they have new messages.
 *
 * Return value: Boolean.
 */
gboolean ggn_preferences_get_notify_new (GgnPreferences* prefs) {
    /* query gconf for the value. */
    gboolean value = gconf_client_get_bool (prefs->priv->conf,
                                            GGN_GPREF_NOTIFY_NEW,
                                            NULL);

    /* return the value. */
    return value;
}

/*
 * ggn_preferences_get_notify_err:
 *
 * Returns whether or not the application will notify the user
 * when an error occurs while accessing their Gmail inbox(es).
 *
 * Return value: Boolean.
 */
gboolean ggn_preferences_get_notify_err (GgnPreferences* prefs) {
    /* query gconf for the value. */
    gboolean value = gconf_client_get_bool (prefs->priv->conf,
                                            GGN_GPREF_NOTIFY_ERR,
                                            NULL);

    /* return the value. */
    return value;
}

/*
 * ggn_preferences_get_sound_enab:
 *
 * Returns whether or not the application will use a sound file
 * to notify the user when they have new messages.
 *
 * Return value: Boolean.
 */
gboolean ggn_preferences_get_sound_enab (GgnPreferences* prefs) {
    /* query gconf for the value. */
    gboolean value = gconf_client_get_bool (prefs->priv->conf,
                                            GGN_GPREF_SOUND_ENAB,
                                            NULL);

    /* return the value. */
    return value;
}

/*
 * ggn_preferences_get_sound_file:
 *
 * Returns the filename of the *.wav sound file which will be
 * played when the user recieves new mail, if the user selected
 * to be notified with sounds.
 *
 * Return value: Sound filename string.
 */
gchar* ggn_preferences_get_sound_file (GgnPreferences* prefs) {
    /* query gconf for the value */
    gchar* value = gconf_client_get_string (prefs->priv->conf,
                                            GGN_GPREF_SOUND_FILE,
                                            NULL);

    /* return a default string if there is no value. */
    if (value == NULL)
        return g_strdup (GGN_DEFAULT_SOUND_FILE);

    /* return the value. */
    return value;
}

/*
 * ggn_preferences_get_firstrun:
 *
 * Returns whether or not this function is running for the
 * first time ever or not. This value will only be TRUE when
 * the user installs their FIRST notifier version.
 *
 * Return value: Boolean.
 */
gboolean ggn_preferences_get_firstrun (GgnPreferences* prefs) {
    /* query gconf for the value */
    gchar* value = gconf_client_get_string (prefs->priv->conf,
                                            GGN_GPREF_FIRSTRUN,
                                            NULL);

    /* return TRUE if gconf returns no value. */
    if (value == NULL)
        return TRUE;

    /* return FALSE if there is a value. */
    g_free (value);
    return FALSE;
}

/*
 * ggn_preferences_set_rate:
 *
 * Sets the update frequency (in minutes) of the application.
 *
 * Return value: void.
 */
void ggn_preferences_set_rate (GgnPreferences* prefs, gint value) {
    /* use gconf to store the value into the database. */
    gconf_client_set_int (prefs->priv->conf,
                          GGN_GPREF_CHECKRATE,
                          value, NULL);
}

/*
 * ggn_preferences_set_notify_new:
 *
 * Sets whether or not to notify on new messages.
 *
 * Return value: void.
 */
void ggn_preferences_set_notify_new (GgnPreferences* prefs, gboolean value) {
    /* use gconf to store the value into the database. */
    gconf_client_set_bool (prefs->priv->conf,
                           GGN_GPREF_NOTIFY_NEW,
                           value, NULL);
}

/*
 * ggn_preferences_set_notify_err:
 *
 * Sets whether or not to notify on errors.
 *
 * Return value: void.
 */
void ggn_preferences_set_notify_err (GgnPreferences* prefs, gboolean value) {
    /* use gconf to store the value into the database. */
    gconf_client_set_bool (prefs->priv->conf,
                           GGN_GPREF_NOTIFY_ERR,
                           value, NULL);
}

/*
 * ggn_preferences_set_sound_enab:
 *
 * Sets whether or not to notify with a sound file.
 *
 * Return value: void.
 */
void ggn_preferences_set_sound_enab (GgnPreferences* prefs, gboolean value) {
    /* use gconf to store the value into the database. */
    gconf_client_set_bool (prefs->priv->conf,
                           GGN_GPREF_SOUND_ENAB,
                           value, NULL);
}

/*
 * ggn_preferences_set_sound_file:
 *
 * Sets the filename of the *.WAV sound file, which is played when
 * the user has more than zero messages in his inbox. (Not necessarily
 * new, however.)
 *
 * Return value: void.
 */
void ggn_preferences_set_sound_file (GgnPreferences* prefs,
                                     const gchar* value) {
    /* check if the sound file is NULL. */
    if (value == NULL)
        value = GGN_DEFAULT_SOUND_FILE;

    /* use gconf to store the value into the database. */
    gconf_client_set_string (prefs->priv->conf,
                             GGN_GPREF_SOUND_FILE,
                             value, NULL);
}

/*
 * ggn_preferences_set_firstrun:
 *
 * Sets the first-run behavior when the application loads up. This is
 * pretty much not even here. Ignore it. It is... INVISIBLE!
 *
 * Return value: void.
 */
void ggn_preferences_set_firstrun (GgnPreferences* prefs, gboolean value) {
    /* see if we're setting to a TRUE value. */
    if (value == TRUE) {
        /* unset the firstrun value. */
        gconf_client_unset (prefs->priv->conf,
                            GGN_GPREF_FIRSTRUN,
                            NULL);
    }
    else {
        /* use gconf to store the value into the database. */
        gconf_client_set_string (prefs->priv->conf,
                                 GGN_GPREF_FIRSTRUN,
                                 "false", NULL);
    }
}

/*
 * ggn_preferences_get_proxy:
 *
 * Returns the proxy server URI in use by the application for
 * its connection to the Gmail server.
 *
 * Return value: Proxy URI string.
 */
gchar* ggn_preferences_get_proxy (GgnPreferences* prefs) {
    /* define a uri string. */
    gchar* uri = NULL;
    
    /* grab the proxy enabled value. */
    gboolean enabled = gconf_client_get_bool (prefs->priv->conf,
                                              GGN_GCONF_PROXY_USE,
                                              NULL);
    
    /* grab the proxy insecure host value. */
    gchar* host = gconf_client_get_string (prefs->priv->conf,
                                           GGN_GCONF_PROXY_HOST,
                                           NULL);
    
    /* grab the proxy insecure port value. */
    gint port = gconf_client_get_int (prefs->priv->conf,
                                      GGN_GCONF_PROXY_PORT,
                                      NULL);
    
    /* grab the proxy secure host value. */
    gchar* ssl_host = gconf_client_get_string (prefs->priv->conf,
                                               GGN_GCONF_PROXY_SSL_HOST,
                                               NULL);
    
    /* grab the proxy secure port value. */
    gint ssl_port = gconf_client_get_int (prefs->priv->conf,
                                          GGN_GCONF_PROXY_SSL_PORT,
                                          NULL);
    
    /* see if the proxy is enabled. */
    if (enabled == TRUE) {
        /* make a qualified string. */
        if ((strlen (ssl_host) > 0) && (ssl_port != 0)) {
            /* use the secure host and port. */
            uri = g_strdup_printf ("http://%s:%d", ssl_host, ssl_port);
        }
        else if ((strlen (host) > 0) && (port != 0)) {
            /* use the regular host and port. */
            uri = g_strdup_printf ("http://%s:%d", host, port);
        }
        else {
            /* return a default. */
            uri = g_strdup ("");
        }
    }
    else {
        /* return a default. */
        uri = g_strdup ("");
    }
    
    /* free the strings we got from gconf. */
    g_free (host);
    g_free (ssl_host);
    
    /* return the final value. */
    return uri;
}

/*
 * ggn_preferences_get_proxy_user:
 *
 * Returns the username for the proxy server.
 *
 * Return value: String
 */
gchar* ggn_preferences_get_proxy_user (GgnPreferences* prefs) {
    /* query gconf for the value. */
    gchar* user = gconf_client_get_string (prefs->priv->conf,
                                           GGN_GCONF_PROXY_USERNAME,
                                           NULL);

    /* return the value. */
    return user;
}

/*
 * ggn_preferences_get_proxy_pass:
 *
 * Returns the password for the proxy server.
 *
 * Return value: String
 */
gchar* ggn_preferences_get_proxy_pass (GgnPreferences* prefs) {
    /* query gconf for the value. */
    gchar* pass = gconf_client_get_string (prefs->priv->conf,
                                           GGN_GCONF_PROXY_PASSWORD,
                                           NULL);

    /* return the value. */
    return pass;
}

